home *** CD-ROM | disk | FTP | other *** search
- <?php
- //
- // +------------------------------------------------------------------------+
- // | PEAR :: Package File Manager |
- // +------------------------------------------------------------------------+
- // | Copyright (c) 2003-2004 Gregory Beaver |
- // | Email cellog@phpdoc.org |
- // +------------------------------------------------------------------------+
- // | This source file is subject to version 3.00 of the PHP License, |
- // | that is available at http://www.php.net/license/3_0.txt. |
- // | If you did not receive a copy of the PHP license and are unable to |
- // | obtain it through the world-wide-web, please send a note to |
- // | license@php.net so we can mail you a copy immediately. |
- // +------------------------------------------------------------------------+
- // | Portions of this code based on phpDocumentor |
- // | Web http://www.phpdoc.org |
- // | Mirror http://phpdocu.sourceforge.net/ |
- // +------------------------------------------------------------------------+
- // $Id: PackageFileManager.php,v 1.42 2005/04/06 22:21:20 cellog Exp $
- //
-
- /**
- * @package PEAR_PackageFileManager
- */
- /**
- * PEAR installer
- */
- require_once 'PEAR/Common.php';
- /**#@+
- * Error Codes
- */
- define('PEAR_PACKAGEFILEMANAGER_NOSTATE', 1);
- define('PEAR_PACKAGEFILEMANAGER_NOVERSION', 2);
- define('PEAR_PACKAGEFILEMANAGER_NOPKGDIR', 3);
- define('PEAR_PACKAGEFILEMANAGER_NOBASEDIR', 4);
- define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND', 5);
- define('PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE', 6);
- define('PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE', 7);
- define('PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE', 8);
- define('PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE', 9);
- define('PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE', 10);
- define('PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST', 11);
- define('PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES', 12);
- define('PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST', 13);
- define('PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS', 14);
- define('PEAR_PACKAGEFILEMANAGER_NOPACKAGE', 15);
- define('PEAR_PACKAGEFILEMANAGER_WRONG_MROLE', 16);
- define('PEAR_PACKAGEFILEMANAGER_NOSUMMARY', 17);
- define('PEAR_PACKAGEFILEMANAGER_NODESC', 18);
- define('PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS', 19);
- define('PEAR_PACKAGEFILEMANAGER_NO_FILES', 20);
- define('PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING', 21);
- define('PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE', 22);
- define('PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE', 23);
- define('PEAR_PACKAGEFILEMANAGER_INVALID_ROLE', 24);
- define('PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE', 25);
- define('PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED', 26);
- define('PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO', 27);
- /**#@-*/
- /**
- * Error messages
- * @global array $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS']
- */
- $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'] =
- array(
- 'en' =>
- array(
- PEAR_PACKAGEFILEMANAGER_NOSTATE =>
- 'Release State (option \'state\') must by specified in PEAR_PackageFileManager setOptions (alpha|beta|stable)',
- PEAR_PACKAGEFILEMANAGER_NOVERSION =>
- 'Release Version (option \'version\') must be specified in PEAR_PackageFileManager setOptions',
- PEAR_PACKAGEFILEMANAGER_NOPKGDIR =>
- 'Package source base directory (option \'packagedirectory\') must be ' .
- 'specified in PEAR_PackageFileManager setOptions',
- PEAR_PACKAGEFILEMANAGER_NOBASEDIR =>
- 'Package install base directory (option \'baseinstalldir\') must be ' .
- 'specified in PEAR_PackageFileManager setOptions',
- PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND =>
- 'Base class "%s" can\'t be located',
- PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE =>
- 'Base class "%s" can\'t be located in default or user-specified directories',
- PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE =>
- 'Failed to write package.xml file to destination directory',
- PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE =>
- 'Destination directory "%s" is unwritable',
- PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE =>
- 'Failed to copy package.xml.tmp file to package.xml',
- PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE =>
- 'Failed to open temporary file "%s" for writing',
- PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST =>
- 'package.xml file path "%s" doesn\'t exist or isn\'t a directory',
- PEAR_PACKAGEFILEMANAGER_NOCVSENTRIES =>
- 'Directory "%s" is not a CVS directory (it must have the CVS/Entries file)',
- PEAR_PACKAGEFILEMANAGER_DIR_DOESNT_EXIST =>
- 'Package source base directory "%s" doesn\'t exist or isn\'t a directory',
- PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS =>
- 'Run $managerclass->setOptions() before any other methods',
- PEAR_PACKAGEFILEMANAGER_NOPACKAGE =>
- 'Package Name (option \'package\') must by specified in PEAR_PackageFileManager '.
- 'setOptions to create a new package.xml',
- PEAR_PACKAGEFILEMANAGER_NOSUMMARY =>
- 'Package Summary (option \'summary\') must by specified in PEAR_PackageFileManager' .
- ' setOptions to create a new package.xml',
- PEAR_PACKAGEFILEMANAGER_NODESC =>
- 'Detailed Package Description (option \'description\') must be' .
- ' specified in PEAR_PackageFileManager setOptions to create a new package.xml',
- PEAR_PACKAGEFILEMANAGER_WRONG_MROLE =>
- 'Maintainer role must be one of "%s", was "%s"',
- PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS =>
- 'Add maintainers to a package before generating the package.xml',
- PEAR_PACKAGEFILEMANAGER_NO_FILES =>
- 'No files found, check the path "%s"',
- PEAR_PACKAGEFILEMANAGER_IGNORED_EVERYTHING =>
- 'No files left, check the path "%s" and ignore option "%s"',
- PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE =>
- 'Package validation failed:%s%s',
- PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE =>
- 'Replacement Type must be one of "%s", was passed "%s"',
- PEAR_PACKAGEFILEMANAGER_INVALID_ROLE =>
- 'Invalid file role passed to addRole, must be one of "%s", was passed "%s"',
- PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE =>
- 'addDependency had PHP as a package, use type="php"',
- PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED =>
- 'path "%path%" contains CVS directory',
- PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO =>
- 'PHP_Compat is not installed, cannot detect dependencies',
- ),
- // other language translations go here
- );
- /**
- * PEAR :: PackageFileManager updates the <filelist></filelist> section
- * of a PEAR package.xml file to reflect the current files in
- * preparation for a release.
- *
- * The PEAR_PackageFileManager class uses a plugin system to generate the
- * list of files in a package. This allows both standard recursive
- * directory parsing (plugin type file) and more intelligent options
- * such as the CVS browser {@link PEAR_PackageFileManager_Cvs}, which
- * grabs all files in a local CVS checkout to create the list, ignoring
- * any other local files.
- *
- * Other options include specifying roles for file extensions (all .php
- * files are role="php", for example), roles for directories (all directories
- * named "tests" are given role="tests" by default), and exceptions.
- * Exceptions are specific pathnames with * and ? wildcards that match
- * a default role, but should have another. For example, perhaps
- * a debug.tpl template would normally be data, but should be included
- * in the docs role. Along these lines, to exclude files entirely,
- * use the ignore option.
- *
- * Required options for a release include version, baseinstalldir, state,
- * and packagedirectory (the full path to the local location of the
- * package to create a package.xml file for)
- *
- * Example usage:
- * <code>
- * <?php
- * require_once('PEAR/PackageFileManager.php');
- * $packagexml = new PEAR_PackageFileManager;
- * $e = $packagexml->setOptions(
- * array('baseinstalldir' => 'PhpDocumentor',
- * 'version' => '1.2.1',
- * 'packagedirectory' => 'C:/Web Pages/chiara/phpdoc2/',
- * 'state' => 'stable',
- * 'filelistgenerator' => 'cvs', // generate from cvs, use file for directory
- * 'notes' => 'We\'ve implemented many new and exciting features',
- * 'ignore' => array('TODO', 'tests/'), // ignore TODO, all files in tests/
- * 'installexceptions' => array('phpdoc' => '/*'), // baseinstalldir ="/" for phpdoc
- * 'dir_roles' => array('tutorials' => 'doc'),
- * 'exceptions' => array('README' => 'doc', // README would be data, now is doc
- * 'PHPLICENSE.txt' => 'doc'))); // same for the license
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * die();
- * }
- * $e = $test->addPlatformException('pear-phpdoc.bat', 'windows');
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * exit;
- * }
- * $packagexml->addRole('pkg', 'doc'); // add a new role mapping
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * exit;
- * }
- * // replace @PHP-BIN@ in this file with the path to php executable! pretty neat
- * $e = $test->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin');
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * exit;
- * }
- * $e = $test->addReplacement('pear-phpdoc.bat', 'pear-config', '@PHP-BIN@', 'php_bin');
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * exit;
- * }
- * // note use of {@link debugPackageFile()} - this is VERY important
- * if (isset($_GET['make']) || (isset($_SERVER['argv'][2]) &&
- * $_SERVER['argv'][2] == 'make')) {
- * $e = $packagexml->writePackageFile();
- * } else {
- * $e = $packagexml->debugPackageFile();
- * }
- * if (PEAR::isError($e)) {
- * echo $e->getMessage();
- * die();
- * }
- * ?>
- * </code>
- *
- * In addition, a package.xml file can now be generated from
- * scratch, with the usage of new options package, summary, description, and
- * the use of the {@link addMaintainer()} method
- * @package PEAR_PackageFileManager
- */
- class PEAR_PackageFileManager
- {
- /**
- * Format: array(array(regexp-ready string to search for whole path,
- * regexp-ready string to search for basename of ignore strings),...)
- * @var false|array
- * @access private
- */
- var $_ignore = false;
-
- /**
- * Contents of the package.xml file
- * @var string
- * @access private
- */
- var $_packageXml = false;
-
- /**
- * Contents of the original package.xml file, if any
- * @var string
- * @access private
- */
- var $_oldPackageXml = false;
-
- /**
- * @access private
- * @var PEAR_Common
- */
- var $_pear;
-
- /**
- * @access private
- * @var array
- */
- var $_warningStack = array();
-
- /**
- * flag used to determine whether to use PHP_CompatInfo to detect deps
- * @var boolean
- * @access private
- */
- var $_detectDependencies = false;
-
- /**
- * @access private
- * @var string
- */
- var $_options = array(
- 'packagefile' => 'package.xml',
- 'doctype' => 'http://pear.php.net/dtd/package-1.0',
- 'filelistgenerator' => 'file',
- 'license' => 'PHP License',
- 'changelogoldtonew' => true,
- 'roles' =>
- array(
- 'php' => 'php',
- 'html' => 'doc',
- '*' => 'data',
- ),
- 'dir_roles' =>
- array(
- 'docs' => 'doc',
- 'examples' => 'doc',
- 'tests' => 'test',
- ),
- 'exceptions' => array(),
- 'installexceptions' => array(),
- 'installas' => array(),
- 'platformexceptions' => array(),
- 'scriptphaseexceptions' => array(),
- 'ignore' => array(),
- 'include' => false,
- 'deps' => false,
- 'maintainers' => false,
- 'notes' => '',
- 'changelognotes' => false,
- 'outputdirectory' => false,
- 'pathtopackagefile' => false,
- 'lang' => 'en',
- 'configure_options' => array(),
- 'replacements' => array(),
- 'pearcommonclass' => false,
- 'simpleoutput' => false,
- 'addhiddenfiles' => false,
- 'cleardependencies' => false,
- );
-
- /**
- * Does nothing, use setOptions
- *
- * The constructor is not used in order to be able to
- * return a PEAR_Error from setOptions
- * @see setOptions()
- */
- function PEAR_PackageFileManager()
- {
- }
-
- /**
- * Set package.xml generation options
- *
- * The options array is indexed as follows:
- * <code>
- * $options = array('option_name' => <optionvalue>);
- * </code>
- *
- * The documentation below simplifies this description through
- * the use of option_name without quotes
- *
- * Configuration options:
- * - lang: lang controls the language in which error messages are
- * displayed. There are currently only English error messages,
- * but any contributed will be added over time.<br>
- * Possible values: en (default)
- * - packagefile: the name of the packagefile, defaults to package.xml
- * - pathtopackagefile: the path to an existing package file to read in,
- * if different from the packagedirectory
- * - packagedirectory: the path to the base directory of the package. For
- * package PEAR_PackageFileManager, this path is
- * /path/to/pearcvs/pear/PEAR_PackageFileManager where
- * /path/to/pearcvs is a local path on your hard drive
- * - outputdirectory: the path in which to place the generated package.xml
- * by default, this is ignored, and the package.xml is
- * created in the packagedirectory
- * - filelistgenerator: the <filelist> section plugin which will be used.
- * In this release, there are two generator plugins,
- * file and cvs. For details, see the docs for these
- * plugins
- * - usergeneratordir: For advanced users. If you write your own filelist
- * generator plugin, use this option to tell
- * PEAR_PackageFileManager where to find the file that
- * contains it. If the plugin is named foo, the class
- * must be named PEAR_PackageFileManager_Foo
- * no matter where it is located. By default, the Foo
- * plugin is located in PEAR/PackageFileManager/Foo.php.
- * If you pass /path/to/foo in this option, setOptions
- * will look for PEAR_PackageFileManager_Foo in
- * /path/to/foo/Foo.php
- * - doctype: Specifies the DTD of the package.xml file. Default is
- * http://pear.php.net/dtd/package-1.0
- * - pearcommonclass: Specifies the name of the class to instantiate, default
- * is PEAR_Common, but users can override this with a custom
- * class that implements PEAR_Common's method interface
- * - changelogoldtonew: True if the ChangeLog should list from oldest entry to
- * newest. Set to false if you would like new entries first
- * - simpleoutput: True if the package.xml should not contain md5sum or <provides />
- * for readability
- * - addhiddenfiles: True if you wish to add hidden files/directories that begin with .
- * like .bashrc. This is only used by the File generator. The CVS
- * generator will use all files in CVS regardless of format
- *
- * package.xml simple options:
- * - baseinstalldir: The base directory to install this package in. For
- * package PEAR_PackageFileManager, this is "PEAR", for
- * package PEAR, this is "/"
- * - license: The license this release is released under. Default is
- * PHP License if left unspecified
- * - notes: Release notes, any text describing what makes this release unique
- * - changelognotes: notes for the changelog, this should be more detailed than
- * the release notes. By default, PEAR_PackageFileManager uses
- * the notes option for the changelog as well
- * - version: The version number for this release. Remember the convention for
- * numbering: initial alpha is between 0 and 1, add b<beta number> for
- * beta as in 1.0b1, the integer portion of the version should specify
- * backwards compatibility, as in 1.1 is backwards compatible with 1.0,
- * but 2.0 is not backwards compatible with 1.10. Also note that 1.10
- * is a greater release version than 1.1 (think of it as "one point ten"
- * and "one point one"). Bugfix releases should be a third decimal as in
- * 1.0.1, 1.0.2
- * - package: [optional] Package name. Use this to create a new package.xml, or
- * overwrite an existing one from another package used as a template
- * - summary: [optional] Summary of package purpose
- * - description: [optional] Description of package purpose. Note that the above
- * three options are not optional when creating a new package.xml
- * from scratch
- *
- * <b>WARNING</b>: all complex options that require a file path are case-sensitive
- *
- * package.xml complex options:
- * - cleardependencies: since version 1.3.0, this option will erase any existing
- * dependencies in the package.xml if set to true
- * - ignore: an array of filenames, directory names, or wildcard expressions specifying
- * files to exclude entirely from the package.xml. Wildcards are operating system
- * wildcards * and ?. file*foo.php will exclude filefoo.php, fileabrfoo.php and
- * filewho_is_thisfoo.php. file?foo.php will exclude fileafoo.php and will not
- * exclude fileaafoo.php. test/ will exclude all directories and subdirectories of
- * ANY directory named test encountered in directory parsing. *test* will exclude
- * all files and directories that contain test in their name
- * - include: an array of filenames, directory names, or wildcard expressions specifying
- * files to include in the listing. All other files will be ignored.
- * Wildcards are in the same format as ignore
- * - roles: this is an array mapping file extension to install role. This
- * specifies default behavior that can be overridden by the exceptions
- * option and dir_roles option. use {@link addRole()} to add a new
- * role to the pre-existing array
- * - dir_roles: this is an array mapping directory name to install role. All
- * files in a directory whose name matches the directory will be
- * given the install role specified. Single files can be excluded
- * from this using the exceptions option. The directory should be
- * a relative path from the baseinstalldir, or "/" for the baseinstalldir
- * - exceptions: specify file role for specific files. This array maps all files
- * matching the exact name of a file to a role as in "file.ext" => "role"
- * - deps: dependency array. Pass in an empty array to clear all dependencies, and use
- * {@link addDependency()} to add new ones/replace existing ones
- * - maintainers: maintainers array. Pass in an empty array to clear all maintainers, and
- * use {@link addMaintainer()} to add a new maintainer/replace existing maintainer
- * - installexceptions: array mapping of specific filenames to baseinstalldir values. Use
- * this to force the installation of a file into another directory,
- * such as forcing a script to be in the root scripts directory so that
- * it will be in the path. The filename must be a relative path to the
- * packagedirectory
- * - platformexceptions: array mapping of specific filenames to the platform they should be
- * installed on. Use this to specify unix-only files or windows-only
- * files. The format of the platform string must be
- * OS-version-cpu-extra if any more specific information is needed,
- * and the OS must be in lower case as in "windows." The match is
- * performed using a regular expression, but uses * and ? wildcards
- * instead of .* and .?. Note that hpux/aix/irix/linux are all
- * exclusive. To select non-windows, use (*ix|*ux)
- * - scriptphaseexceptions: array mapping of scripts to their install phase. This can be
- * one of: pre-install, post-install, pre-uninstall, post-uninstall,
- * pre-build, post-build, pre-setup, or post-setup
- * - installas: array mapping of specific filenames to the filename they should be installed as.
- * Use this to specify new filenames for files that should be installed. This will
- * often be used in conjunction with platformexceptions if there are two files for
- * different OSes that must have the same name when installed.
- * - replacements: array mapping of specific filenames to complex text search-and-replace that
- * should be performed upon install. The format is:
- * <pre>
- * filename => array('type' => php-const|pear-config|package-info
- * 'from' => text in file
- * 'to' => name of variable)
- * </pre>
- * if type is php-const, then 'to' must be the name of a PHP Constant.
- * If type is pear-config, then 'to' must be the name of a PEAR config
- * variable accessible through a PEAR_Config class->get() method. If
- * type is package-info, then 'to' must be the name of a section from
- * the package.xml file used to install this file.
- * - globalreplacements: a list of replacements that should be performed on every single file.
- * The format is the same as replacements (since 1.4.0)
- * - configure_options: array specifies build options for PECL packages (you should probably
- * use PECL_Gen instead, but it's here for completeness)
- * @see PEAR_PackageFileManager_File
- * @see PEAR_PackageFileManager_CVS
- * @return void|PEAR_Error
- * @throws PEAR_PACKAGEFILEMANAGER_NOSTATE
- * @throws PEAR_PACKAGEFILEMANAGER_NOVERSION
- * @throws PEAR_PACKAGEFILEMANAGER_NOPKGDIR
- * @throws PEAR_PACKAGEFILEMANAGER_NOBASEDIR
- * @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE
- * @throws PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND
- * @param array
- */
- function setOptions($options = array(), $internal = false)
- {
- if (!$internal) {
- if (!isset($options['state'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSTATE);
- }
- if (!isset($options['version'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOVERSION);
- }
- }
- if (!isset($options['packagedirectory']) && !$internal) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPKGDIR);
- } elseif (isset($options['packagedirectory'])) {
- $options['packagedirectory'] = str_replace(DIRECTORY_SEPARATOR,
- '/',
- realpath($options['packagedirectory']));
- if ($options['packagedirectory']{strlen($options['packagedirectory']) - 1} != '/') {
- $options['packagedirectory'] .= '/';
- }
- }
- if (isset($options['pathtopackagefile'])) {
- $options['pathtopackagefile'] = str_replace(DIRECTORY_SEPARATOR,
- '/',
- realpath($options['pathtopackagefile']));
- if ($options['pathtopackagefile']{strlen($options['pathtopackagefile']) - 1} != '/') {
- $options['pathtopackagefile'] .= '/';
- }
- }
- if (!isset($options['baseinstalldir']) && !$internal) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOBASEDIR);
- }
- $this->_options = array_merge($this->_options, $options);
-
- if (!class_exists($this->_options['pearcommonclass'])) {
- if ($this->_options['simpleoutput']) {
- if ($this->isIncludeable('PEAR/PackageFile/Generator/v1.php')) {
- include_once 'PEAR/PackageFileManager/SimpleGenerator.php';
- $this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_SimpleGenerator';
- } else {
- include_once 'PEAR/PackageFileManager/XMLOutput.php';
- $this->_options['pearcommonclass'] = 'PEAR_PackageFileManager_XMLOutput';
- }
- } else {
- $this->_options['pearcommonclass'] = 'PEAR_Common';
- }
- }
- $path = ($this->_options['pathtopackagefile'] ?
- $this->_options['pathtopackagefile'] : $this->_options['packagedirectory']);
- $this->_options['filelistgenerator'] =
- ucfirst(strtolower($this->_options['filelistgenerator']));
- if (!$internal) {
- if (PEAR::isError($res =
- $this->_getExistingPackageXML($path, $this->_options['packagefile']))) {
- return $res;
- }
- }
- if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
- // attempt to load the interface from the standard PEAR location
- if ($this->isIncludeable('PEAR/PackageFileManager/' .
- $this->_options['filelistgenerator'] . '.php')) {
- include_once('PEAR/PackageFileManager/' .
- $this->_options['filelistgenerator'] . '.php');
- } elseif (isset($this->_options['usergeneratordir'])) {
- // attempt to load from a user-specified directory
- if (is_dir(realpath($this->_options['usergeneratordir']))) {
- $this->_options['usergeneratordir'] =
- str_replace(DIRECTORY_SEPARATOR,
- '/',
- realpath($this->_options['usergeneratordir']));
- if ($this->_options['usergeneratordir']{strlen($this->_options['usergeneratordir'])
- - 1} != '/') {
- $this->_options['usergeneratordir'] .= '/';
- }
- } else {
- $this->_options['usergeneratordir'] = '////';
- }
- if (file_exists($this->_options['usergeneratordir'] .
- $this->_options['filelistgenerator'] . '.php') &&
- is_readable($this->_options['usergeneratordir'] .
- $this->_options['filelistgenerator'] . '.php')) {
- include_once($this->_options['usergeneratordir'] .
- $this->_options['filelistgenerator'] . '.php');
- }
- if (!class_exists('PEAR_PackageFileManager_' . $this->_options['filelistgenerator'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND_ANYWHERE,
- 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
- }
- } else {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_GENERATOR_NOTFOUND,
- 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator']);
- }
- }
- }
-
- /**
- * Import options from an existing package.xml
- *
- * @return true|PEAR_Error
- */
- function importOptions($packagefile, $options = array())
- {
- $options['cleardependencies'] = $options['deps'] = $options['maintainers'] = false;
- $this->setOptions($options, true);
- if (PEAR::isError($res = $this->_getExistingPackageXML(dirname($packagefile) .
- DIRECTORY_SEPARATOR, basename($packagefile)))) {
- return $res;
- }
- $this->_options['package'] = $this->_oldPackageXml['package'];
- $this->_options['summary'] = $this->_oldPackageXml['summary'];
- $this->_options['description'] = $this->_oldPackageXml['description'];
- $this->_options['date'] = $this->_oldPackageXml['release_date'];
- $this->_options['version'] = $this->_oldPackageXml['version'];
- $this->_options['license'] = $this->_oldPackageXml['release_license'];
- $this->_options['state'] = $this->_oldPackageXml['release_state'];
- $this->_options['notes'] = $this->_oldPackageXml['release_notes'];
- if (isset($this->_oldPackagexml['release_deps'])) {
- $this->_options['deps'] = $this->_oldPackageXml['release_deps'];
- }
- $this->_options['maintainers'] = $this->_oldPackageXml['maintainers'];
- return true;
- }
-
- /**
- * Get the existing options
- * @return array
- */
- function getOptions()
- {
- return $this->_options;
- }
-
- /**
- * Add an extension/role mapping to the role mapping option
- *
- * Roles influence both where a file is installed and how it is installed.
- * Files with role="data" are in a completely different directory hierarchy
- * from the program files of role="php"
- *
- * In PEAR 1.3b2, these roles are
- * - php (most common)
- * - data
- * - doc
- * - test
- * - script (gives the file an executable attribute)
- * - src
- * @param string file extension
- * @param string role
- * @throws PEAR_PACKAGEFILEMANAGER_INVALID_ROLE
- */
- function addRole($extension, $role)
- {
- $roles = call_user_func(array($this->_options['pearcommonclass'], 'getfileroles'));
- if (!in_array($role, $roles)) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_ROLE, implode($roles, ', '), $role);
- }
- $this->_options['roles'][$extension] = $role;
- }
-
- /**
- * Add an install-time platform conditional install for a file
- *
- * The format of the platform string must be
- * OS-version-cpu-extra if any more specific information is needed,
- * and the OS must be in lower case as in "windows." The match is
- * performed using a regular expression, but uses * and ? wildcards
- * instead of .* and .?. Note that hpux/aix/irix/linux are all
- * exclusive. To select non-windows, use (*ix|*ux)
- *
- * This information is based on eyeing the source for OS/Guess.php, so
- * if you are unsure of what to do, read that file.
- * @param string relative path of file (relative to packagedirectory option)
- * @param string platform descriptor string
- */
- function addPlatformException($path, $platform)
- {
- if (!isset($this->_options['platformexceptions'])) {
- $this->_options['platformexceptions'] = array();
- }
- $this->_options['platformexceptions'][$path] = $platform;
- }
-
- /**
- * Add a replacement option for all files
- *
- * This sets an install-time complex search-and-replace function
- * allowing the setting of platform-specific variables in all
- * installed files.
- *
- * if $type is php-const, then $to must be the name of a PHP Constant.
- * If $type is pear-config, then $to must be the name of a PEAR config
- * variable accessible through a {@link PEAR_Config::get()} method. If
- * type is package-info, then $to must be the name of a section from
- * the package.xml file used to install this file.
- * @param string relative path of file (relative to packagedirectory option)
- * @param string variable type, either php-const, pear-config or package-info
- * @param string text to replace in the source file
- * @param string variable name to use for replacement
- * @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE
- */
- function addGlobalReplacement($type, $from, $to)
- {
- if (!isset($this->_options['globalreplacements'])) {
- $this->_options['globalreplacements'] = array();
- }
- $types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes'));
- if (!in_array($type, $types)) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE,
- implode($types, ', '), $type);
- }
- $this->_options['globalreplacements'][] =
- array('type' => $type, 'from' => $from, 'to' => $to);
- }
-
- /**
- * Add a replacement option for a file
- *
- * This sets an install-time complex search-and-replace function
- * allowing the setting of platform-specific variables in an
- * installed file.
- *
- * if $type is php-const, then $to must be the name of a PHP Constant.
- * If $type is pear-config, then $to must be the name of a PEAR config
- * variable accessible through a {@link PEAR_Config::get()} method. If
- * type is package-info, then $to must be the name of a section from
- * the package.xml file used to install this file.
- * @param string relative path of file (relative to packagedirectory option)
- * @param string variable type, either php-const, pear-config or package-info
- * @param string text to replace in the source file
- * @param string variable name to use for replacement
- * @throws PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE
- */
- function addReplacement($path, $type, $from, $to)
- {
- if (!isset($this->_options['replacements'])) {
- $this->_options['replacements'] = array();
- }
- $types = call_user_func(array($this->_options['pearcommonclass'], 'getreplacementtypes'));
- if (!in_array($type, $types)) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_REPLACETYPE,
- implode($types, ', '), $type);
- }
- $this->_options['replacements'][$path][] = array('type' => $type, 'from' => $from, 'to' => $to);
- }
-
- /**
- * Add a maintainer to the list of maintainers.
- *
- * Every maintainer must have a valid account at pear.php.net. The
- * first parameter is the account name (for instance, cellog is the
- * handle for Greg Beaver at pear.php.net). Every maintainer has
- * one of four possible roles:
- * - lead: the primary maintainer
- * - developer: an important developer on the project
- * - contributor: self-explanatory
- * - helper: ditto
- *
- * Finally, specify the name and email of the maintainer
- * @param string username on pear.php.net of maintainer
- * @param lead|developer|contributor|helper role of maintainer
- * @param string full name of maintainer
- * @param string email address of maintainer
- */
- function addMaintainer($handle, $role, $name, $email)
- {
- if (!$this->_packageXml) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- if (!in_array($role, $GLOBALS['_PEAR_Common_maintainer_roles'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_WRONG_MROLE,
- implode(', ', call_user_func(array($this->_options['pearcommonclass'],
- 'getUserRoles'))),
- $role);
- }
- if (!isset($this->_packageXml['maintainers'])) {
- $this->_packageXml['maintainers'] = array();
- }
- $found = false;
- foreach($this->_packageXml['maintainers'] as $index => $maintainer) {
- if ($maintainer['handle'] == $handle) {
- $found = $index;
- break;
- }
- }
- $maintainer =
- array('handle' => $handle, 'role' => $role, 'name' => $name, 'email' => $email);
- if ($found !== false) {
- $this->_packageXml['maintainers'][$found] = $maintainer;
- } else {
- $this->_packageXml['maintainers'][] = $maintainer;
- }
- }
-
- /**
- * Add an install-time configuration option for building of source
- *
- * This option is only useful to PECL projects that are built upon
- * installation
- * @param string name of the option
- * @param string prompt to display to the user
- * @param string default value
- * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
- * @return void|PEAR_Error
- */
- function addConfigureOption($name, $prompt, $default = null)
- {
- if (!$this->_packageXml) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- if (!isset($this->_packageXml['configure_options'])) {
- $this->_packageXml['configure_options'] = array();
- }
- $found = false;
- foreach($this->_packageXml['configure_options'] as $index => $option) {
- if ($option['name'] == $name) {
- $found = $index;
- break;
- }
- }
- $option = array('name' => $name, 'prompt' => $prompt);
- if (isset($default)) {
- $option['default'] = $default;
- }
- if ($found !== false) {
- $this->_packageXml['configure_options'][$found] = $option;
- } else {
- $this->_packageXml['configure_options'][] = $option;
- }
- }
-
- /**
- * @return void|PEAR_Error
- * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
- */
- function detectDependencies()
- {
- if (!$this->_packageXml) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- if (!$this->isIncludeable('PHP/CompatInfo.php')) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_COMPAT_NOT_INSTALLED);
- } else {
- if (include_once('PHP/CompatInfo.php')) {
- $this->_detectDependencies = true;
- } else {
- $this->raiseError(PEAR_PACKAGEFILEMANAGER_NO_PHPCOMPATINFO);
- }
- }
- }
-
- function isIncludeable($file)
- {
- if (!defined('PATH_SEPARATOR')) {
- define('PATH_SEPARATOR', strtolower(substr(PHP_OS, 0, 3)) == 'win' ? ';' : ':');
- }
- foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $path) {
- if (file_exists($path . DIRECTORY_SEPARATOR . $file) &&
- is_readable($path . DIRECTORY_SEPARATOR . $file)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Add a dependency on another package, or an extension/php
- *
- * This will overwrite an existing dependency if it is found. In
- * other words, if a dependency on PHP 4.1.0 exists, and
- * addDependency('php', '4.3.0', 'ge', 'php') is called, the existing
- * dependency on PHP 4.1.0 will be overwritten with the new one on PHP 4.3.0
- * @param string Dependency element name
- * @param string Dependency version
- * @param string A specific operator for the version, this can be one of:
- * 'has', 'not', 'lt', 'le', 'eq', 'ne', 'ge', or 'gt'
- * @param string Dependency type. This can be one of:
- * 'pkg', 'ext', 'php', 'prog', 'os', 'sapi', or 'zend'
- * @param boolean true if dependency is optional
- * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
- * @throws PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE
- * @return void|PEAR_Error
- */
- function addDependency($name, $version = false, $operator = 'ge', $type = 'pkg', $optional = false)
- {
- if (!$this->_packageXml) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- if ((strtolower($name) == 'php') && (strtolower($type) == 'pkg')) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PHP_NOT_PACKAGE);
- }
- if (!isset($this->_packageXml['release_deps']) || !is_array($this->_packageXml['release_deps'])) {
- $this->_packageXml['release_deps'] = array();
- }
- $found = false;
- foreach($this->_packageXml['release_deps'] as $index => $dep) {
- if ($type == 'php') {
- if ($dep['type'] == 'php') {
- $found = $index;
- break;
- }
- } else {
- if (isset($dep['name']) && $dep['name'] == $name && $dep['type'] == $type) {
- $found = $index;
- break;
- }
- }
- }
- $dep =
- array(
- 'name' => $name,
- 'type' => $type);
- if ($type == 'php') {
- unset($dep['name']);
- }
- if ($operator) {
- $dep['rel'] = $operator;
- if ($dep['rel'] != 'has' && $version) {
- $dep['version'] = $version;
- }
- }
-
- if ($optional) {
- $dep['optional'] = 'yes';
- } else {
- $dep['optional'] = 'no';
- }
-
- if ($found !== false) {
- $this->_packageXml['release_deps'][$found] = $dep; // overwrite existing dependency
- } else {
- $this->_packageXml['release_deps'][] = $dep; // add new dependency
- }
- }
-
- /**
- * Writes the package.xml file out with the newly created <release></release> tag
- *
- * ALWAYS use {@link debugPackageFile} to verify that output is correct before
- * overwriting your package.xml
- * @param boolean null if no debugging, true if web interface, false if command-line
- * @throws PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS
- * @throws PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS
- * @throws PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE
- * @throws PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE
- * @throws PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE
- * @throws PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE
- * @return void|PEAR_Error
- */
- function writePackageFile($debuginterface = null)
- {
- if (!$this->_packageXml) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- if (!isset($this->_packageXml['maintainers']) || empty($this->_packageXml['maintainers'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_ADD_MAINTAINERS);
- }
- extract($this->_options);
- $date = date('Y-m-d');
- if (isset($package)) {
- $this->_packageXml['package'] = $package;
- }
- if (isset($summary)) {
- $this->_packageXml['summary'] = $summary;
- }
- if (isset($description)) {
- $this->_packageXml['description'] = $description;
- }
- $this->_packageXml['release_date'] = $date;
- $this->_packageXml['version'] = $version;
- $this->_packageXml['release_license'] = $license;
- $this->_packageXml['release_state'] = $state;
- $this->_packageXml['release_notes'] = $notes;
- $PEAR_Common = $this->_options['pearcommonclass'];
- $this->_pear = new $PEAR_Common;
- if (method_exists($this->_pear, 'setPackageFileManager')) {
- $this->_pear->setPackageFileManager($this);
- }
- $this->_packageXml['filelist'] = $this->_getFileList();
- $warnings = $this->getWarnings();
- if (count($warnings)) {
- $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
- foreach($warnings as $errmsg) {
- echo 'WARNING: ' . $errmsg['message'] . $nl;
- }
- }
- if (PEAR::isError($this->_packageXml['filelist'])) {
- return $this->_packageXml['filelist'];
- }
- if (isset($this->_pear->pkginfo['provides'])) {
- $this->_packageXml['provides'] = $this->_pear->pkginfo['provides'];
- }
- if ($this->_options['simpleoutput']) {
- unset($this->_packageXml['provides']);
- }
- $this->_packageXml['release_deps'] = $this->_getDependencies();
- $this->_updateChangeLog();
-
- $common = &$this->_pear;
- $warnings = $errors = array();
- if (method_exists($common, 'setPackageFileManagerOptions')) {
- $common->setPackageFileManagerOptions($this->_options);
- }
- $packagexml = $common->xmlFromInfo($this->_packageXml);
- $common->validatePackageInfo($packagexml, $warnings, $errors,
- $this->_options['packagedirectory']);
- if (count($errors)) {
- $ret = '';
- $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
- foreach($errors as $errmsg) {
- $ret .= $errmsg . $nl;
- }
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_INVALID_PACKAGE, $nl, $ret);
- }
- if (count($warnings)) {
- $nl = (isset($debuginterface) && $debuginterface ? '<br />' : "\n");
- foreach($warnings as $errmsg) {
- echo $errmsg . $nl;
- }
- }
- if (!strpos($packagexml, '<!DOCTYPE')) {
- // hack to fix pear
- $packagexml = str_replace('<package version="1.0">',
- '<!DOCTYPE package SYSTEM "' . $this->_options['doctype'] .
- "\">\n<package version=\"1.0\">",
- $packagexml);
- }
- if (isset($debuginterface)) {
- if ($debuginterface) {
- echo '<pre>' . htmlentities($packagexml) . '</pre>';
- } else {
- echo $packagexml;
- }
- return true;
- }
- $outputdir = ($this->_options['outputdirectory'] ?
- $this->_options['outputdirectory'] : $this->_options['packagedirectory']);
- if ((file_exists($outputdir . $this->_options['packagefile']) &&
- is_writable($outputdir . $this->_options['packagefile']))
- ||
- @touch($outputdir . $this->_options['packagefile'])) {
- if ($fp = @fopen($outputdir . $this->_options['packagefile'] . '.tmp', "w")) {
- $written = @fwrite($fp, $packagexml);
- @fclose($fp);
- if ($written === false) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTWRITE_PKGFILE);
- }
- if (!@copy($outputdir . $this->_options['packagefile'] . '.tmp',
- $outputdir . $this->_options['packagefile'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTCOPY_PKGFILE);
- } else {
- @unlink($outputdir . $this->_options['packagefile'] . '.tmp');
- return true;
- }
- } else {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_CANTOPEN_TMPPKGFILE,
- $outputdir . $this->_options['packagefile'] . '.tmp');
- }
- } else {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_DEST_UNWRITABLE, $outputdir);
- }
- }
-
- /**
- * ALWAYS use this to test output before overwriting your package.xml!!
- *
- * This method instructs writePackageFile() to simply print the package.xml
- * to output, either command-line or web-friendly (this is automatic
- * based on the value of php_sapi_name())
- * @uses writePackageFile() calls with the debug parameter set based on
- * whether it is called from the command-line or web interface
- */
- function debugPackageFile()
- {
- $webinterface = php_sapi_name() != 'cli';
- return $this->writePackageFile($webinterface);
- }
-
- /**
- * Store a warning on the warning stack
- */
- function pushWarning($code, $info)
- {
- $this->_warningStack[] = array('code' => $code,
- 'message' => $this->_getMessage($code, $info));
- }
-
- /**
- * Retrieve the list of warnings
- * @return array
- */
- function getWarnings()
- {
- $a = $this->_warningStack;
- $this->_warningStack = array();
- return $a;
- }
-
- /**
- * Retrieve an error message from a code
- * @access private
- * @return string Error message
- */
- function _getMessage($code, $info)
- {
- $msg = $GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code];
- foreach ($info as $name => $value) {
- $msg = str_replace('%' . $name . '%', $value, $msg);
- }
- return $msg;
- }
-
- /**
- * Utility function to shorten error generation code
- *
- * {@source}
- * @return PEAR_Error
- * @static
- */
- function raiseError($code, $i1 = '', $i2 = '')
- {
- return PEAR::raiseError('PEAR_PackageFileManager Error: ' .
- sprintf($GLOBALS['_PEAR_PACKAGEFILEMANAGER_ERRORS'][$this->_options['lang']][$code],
- $i1, $i2), $code);
- }
-
- /**
- * Uses {@link PEAR_Common::analyzeSourceCode()} and {@link PEAR_Common::buildProvidesArray()}
- * to create the <provides></provides> section of the package.xml
- * @param PEAR_Common
- * @param string path to source file
- * @access private
- */
- function _addProvides(&$pear, $file)
- {
- if (!($a = $pear->analyzeSourceCode($file))) {
- return;
- } else {
- $pear->buildProvidesArray($a);
- }
- }
-
- /**
- * @uses getDirTag() generate the xml from the array
- * @return string
- * @access private
- */
- function _getFileList()
- {
- $generatorclass = 'PEAR_PackageFileManager_' . $this->_options['filelistgenerator'];
- $generator = new $generatorclass($this, $this->_options);
- if ($this->_options['simpleoutput'] && is_a($this->_pear, 'PEAR_Common')) {
- return $this->_getSimpleDirTag($this->_struc = $generator->getFileList());
- }
- return $this->_getDirTag($this->_struc = $generator->getFileList());
- }
-
- /**
- * Recursively generate the <filelist> section's <dir> and <file> tags, but with
- * simple human-readable output
- * @param array|PEAR_Error the sorted directory structure, or an error
- * from filelist generation
- * @param false|string whether the parent directory has a role this should
- * inherit
- * @param integer indentation level
- * @return array|PEAR_Error
- * @access private
- */
- function _getSimpleDirTag($struc, $role = false, $_curdir = '')
- {
- if (PEAR::isError($struc)) {
- return $struc;
- }
- extract($this->_options);
- $ret = array();
- foreach($struc as $dir => $files) {
- if (false && $dir === '/') {
- // global directory role? overrides all exceptions except file exceptions
- if (isset($dir_roles['/'])) {
- $role = $dir_roles['/'];
- }
- return array(
- 'baseinstalldir' => $this->_options['baseinstalldir'],
- '##files' => $this->_getSimpleDirTag($struc[$dir], $role, ''),
- 'name' => '/');
- } else {
- if (!isset($files['file'])) {
- if (isset($dir_roles[$_curdir . $dir])) {
- $myrole = $dir_roles[$_curdir . $dir];
- } else {
- $myrole = $role;
- }
- $ret[$dir] = array();
- if ($dir == '/') {
- $ret[$dir]['baseinstalldir'] = $this->_options['baseinstalldir'];
- }
- $ret[$dir]['name'] = $dir;
- $recurdir = ($_curdir == '') ? $dir . '/' : $_curdir . $dir . '/';
- if ($recurdir == '//') {
- $recurdir = '';
- }
- $ret[$dir]['##files'] = $this->_getSimpleDirTag($files, $myrole, $recurdir);
- } else {
- $myrole = '';
- if (!$role)
- {
- $myrole = false;
- if (isset($exceptions[$files['path']])) {
- $myrole = $exceptions[$files['path']];
- } elseif (isset($roles[$files['ext']])) {
- $myrole = $roles[$files['ext']];
- } else {
- $myrole = $roles['*'];
- }
- } else {
- $myrole = $role;
- if (isset($exceptions[$files['path']])) {
- $myrole = $exceptions[$files['path']];
- }
- }
- $test = explode('/', $files['path']);
- foreach ($test as $subpath) {
- if ($subpath == 'CVS') {
- $this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED,
- array('path' => $files['path']));
- }
- }
- $ret[$files['file']] = array('role' => $myrole);
- if (isset($installexceptions[$files['path']])) {
- $ret[$files['file']]['baseinstalldir'] =
- $installexceptions[$files['path']];
- }
- if (isset($platformexceptions[$files['path']])) {
- $ret[$files['file']]['platform'] = $platformexceptions[$files['path']];
- }
- if (isset($installas[$files['path']])) {
- $ret[$files['file']]['install-as'] = $installas[$files['path']];
- }
- if (isset($replacements[$files['path']])) {
- $ret[$files['file']]['replacements'] = $replacements[$files['path']];
- }
- if (isset($globalreplacements)) {
- if (!isset($ret[$files['file']]['replacements'])) {
- $ret[$files['file']]['replacements'] = array();
- }
- $ret[$files['file']]['replacements'] = array_merge(
- $ret[$files['file']]['replacements'], $globalreplacements);
- }
- }
- }
- }
- return $ret;
- }
-
- /**
- * Recursively generate the <filelist> section's <dir> and <file> tags
- * @param array|PEAR_Error the sorted directory structure, or an error
- * from filelist generation
- * @param false|string whether the parent directory has a role this should
- * inherit
- * @param integer indentation level
- * @return array|PEAR_Error
- * @access private
- */
- function _getDirTag($struc, $role=false, $_curdir = '')
- {
- if (PEAR::isError($struc)) {
- return $struc;
- }
- extract($this->_options);
- $ret = array();
- foreach($struc as $dir => $files) {
- if ($dir === '/') {
- // global directory role? overrides all exceptions except file exceptions
- if (isset($dir_roles['/'])) {
- $role = $dir_roles['/'];
- }
- return $this->_getDirTag($struc[$dir], $role, '');
- } else {
- if (!isset($files['file'])) {
- $myrole = '';
- if (isset($dir_roles[$_curdir . $dir])) {
- $myrole = $dir_roles[$_curdir . $dir];
- } elseif ($role) {
- $myrole = $role;
- }
- $ret = array_merge($ret, $this->_getDirTag($files, $myrole, $_curdir . $dir . '/'));
- } else {
- $myrole = '';
- if (!$role)
- {
- $myrole = false;
- if (isset($exceptions[$files['path']])) {
- $myrole = $exceptions[$files['path']];
- } elseif (isset($roles[$files['ext']])) {
- $myrole = $roles[$files['ext']];
- } else {
- $myrole = $roles['*'];
- }
- } else {
- $myrole = $role;
- if (isset($exceptions[$files['path']])) {
- $myrole = $exceptions[$files['path']];
- }
- }
- if (isset($installexceptions[$files['path']])) {
- $bi = $installexceptions[$files['path']];
- } else {
- $bi = $this->_options['baseinstalldir'];
- }
- $test = explode('/', $files['path']);
- foreach ($test as $subpath) {
- if ($subpath == 'CVS') {
- $this->pushWarning(PEAR_PACKAGEFILEMANAGER_CVS_PACKAGED, array('path' => $files['path']));
- }
- }
- $ret[$files['path']] =
- array('role' => $myrole,
- 'baseinstalldir' => $bi,
- );
- if (!isset($this->_options['simpleoutput'])) {
- $md5sum = @md5_file($this->_options['packagedirectory'] . $files['path']);
- if (!empty($md5sum)) {
- $ret[$files['path']]['md5sum'] = $md5sum;
- }
- } elseif (isset($ret[$files['path']]['md5sum'])) {
- unset($ret[$files['path']]['md5sum']);
- }
- if (isset($platformexceptions[$files['path']])) {
- $ret[$files['path']]['platform'] = $platformexceptions[$files['path']];
- }
- if (isset($installas[$files['path']])) {
- $ret[$files['path']]['install-as'] = $installas[$files['path']];
- }
- if (isset($replacements[$files['path']])) {
- $ret[$files['path']]['replacements'] = $replacements[$files['path']];
- }
- if (isset($globalreplacements)) {
- if (!isset($ret[$files['path']]['replacements'])) {
- $ret[$files['path']]['replacements'] = array();
- }
- $ret[$files['path']]['replacements'] = array_merge(
- $ret[$files['path']]['replacements'], $globalreplacements);
- }
- if ($myrole == 'php' && !$this->_options['simpleoutput']) {
- $this->_addProvides($this->_pear, $files['fullpath']);
- }
- }
- }
- }
- return $ret;
- }
-
- /**
- * @param array
- * @access private
- */
- function _traverseFileArray($files, &$ret) {
- foreach ($files as $file) {
- if (!isset($file['fullpath'])) {
- $this->_traverseFileArray($file, $ret);
- } else {
- $ret[] = $file['fullpath'];
- }
- }
- }
-
- /**
- * Retrieve the 'deps' option passed to the constructor
- * @access private
- * @return array
- */
- function _getDependencies()
- {
- if ($this->_detectDependencies) {
- $this->_traverseFileArray($this->_struc, $ret);
- $compatinfo = new PHP_CompatInfo();
- $info = $compatinfo->parseArray($ret);
- $ret = $this->addDependency('php',$info['version'],'ge','php',false);
- if (is_a($ret, 'PEAR_Error')) {
- return $ret;
- }
- foreach ($info['extensions'] as $ext) {
- $this->addDependency($ext, '', 'has', 'ext', false);
- }
- }
- if (isset($this->_packageXml['release_deps']) &&
- is_array($this->_packageXml['release_deps'])) {
- return $this->_packageXml['release_deps'];
- } else {
- return array();
- }
- }
-
- /**
- * Creates a changelog entry with the current release
- * notes and dates, or overwrites a previous creation
- * @access private
- */
- function _updateChangeLog()
- {
- $curlog = $oldchangelog = false;
- if (!isset($this->_packageXml['changelog'])) {
- $changelog = array();
- if (isset($this->_oldPackageXml['release_notes'])) {
- $changelog['release_notes'] = $this->_oldPackageXml['release_notes'];
- }
- if (isset($this->_oldPackageXml['version'])) {
- $changelog['version'] = $this->_oldPackageXml['version'];
- }
- if (isset($this->_oldPackageXml['release_date'])) {
- $changelog['release_date'] = $this->_oldPackageXml['release_date'];
- }
- if (isset($this->_oldPackageXml['release_license'])) {
- $changelog['release_license'] = $this->_oldPackageXml['release_license'];
- }
- if (isset($this->_oldPackageXml['release_state'])) {
- $changelog['release_state'] = $this->_oldPackageXml['release_state'];
- }
- if (count($changelog)) {
- $this->_packageXml['changelog'] = array($changelog);
- } else {
- $this->_packageXml['changelog'] = array();
- }
- } else {
- if (isset($this->_oldPackageXml['release_notes'])) {
- $oldchangelog['release_notes'] = $this->_oldPackageXml['release_notes'];
- }
- if (isset($this->_oldPackageXml['version'])) {
- $oldchangelog['version'] = $this->_oldPackageXml['version'];
- }
- if (isset($this->_oldPackageXml['release_date'])) {
- $oldchangelog['release_date'] = $this->_oldPackageXml['release_date'];
- }
- if (isset($this->_oldPackageXml['release_license'])) {
- $oldchangelog['release_license'] = $this->_oldPackageXml['release_license'];
- }
- if (isset($this->_oldPackageXml['release_state'])) {
- $oldchangelog['release_state'] = $this->_oldPackageXml['release_state'];
- }
- }
- $hasoldversion = false;
- foreach($this->_packageXml['changelog'] as $index => $changelog) {
- if ($oldchangelog && isset($oldchangelog['version'])
- && strnatcasecmp($oldchangelog['version'], $changelog['version']) == 0) {
- $hasoldversion = true;
- }
- if (isset($changelog['version']) && strnatcasecmp($changelog['version'], $this->_options['version']) == 0) {
- $curlog = $index;
- }
- if (isset($this->_packageXml['changelog'][$index]['release_notes'])) {
- $this->_packageXml['changelog'][$index]['release_notes'] = trim($changelog['release_notes']);
- }
- // the parsing of the release notes adds a \n for some reason
- }
- if (!$hasoldversion && $oldchangelog && count($oldchangelog)
- && $oldchangelog['version'] != $this->_options['version']) {
- $this->_packageXml['changelog'][] = $oldchangelog;
- }
- $notes = ($this->_options['changelognotes'] ?
- $this->_options['changelognotes'] : $this->_options['notes']);
- $changelog = array('version' => $this->_options['version'],
- 'release_date' => date('Y-m-d'),
- 'release_license' => $this->_options['license'],
- 'release_state' => $this->_options['state'],
- 'release_notes' => $notes,
- );
- if ($curlog !== false) {
- $this->_packageXml['changelog'][$curlog] = $changelog;
- } else {
- $this->_packageXml['changelog'][] = $changelog;
- }
- usort($this->_packageXml['changelog'], array($this, '_changelogsort'));
- }
-
- /**
- * @static
- * @access private
- */
- function _changelogsort($a, $b)
- {
- if ($this->_options['changelogoldtonew']) {
- $c = strtotime($a['release_date']);
- $d = strtotime($b['release_date']);
- $v1 = $a['version'];
- $v2 = $b['version'];
- } else {
- $d = strtotime($a['release_date']);
- $c = strtotime($b['release_date']);
- $v2 = $a['version'];
- $v1 = $b['version'];
- }
- if ($c - $d > 0) {
- return 1;
- } elseif ($c - $d < 0) {
- return -1;
- }
- return version_compare($v1, $v2);
- }
-
- /**
- * @return true|PEAR_Error
- * @uses _generateNewPackageXML() if no package.xml is found, it
- * calls this to create a new one
- * @param string full path to package file
- * @param string name of package file
- * @throws PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST
- * @access private
- */
- function _getExistingPackageXML($path, $packagefile = 'package.xml')
- {
- if (is_string($path) && is_dir($path)) {
- $contents = false;
- if (file_exists($path . $packagefile)) {
- $contents = file_get_contents($path . $packagefile);
- }
- if (!$contents) {
- return $this->_generateNewPackageXML();
- } else {
- $PEAR_Common = $this->_options['pearcommonclass'];
- if (!class_exists($PEAR_Common)) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_RUN_SETOPTIONS);
- }
- $common = new $PEAR_Common;
- if (is_a($common, 'PEAR_Common')) {
- $this->_oldPackageXml =
- $this->_packageXml = $common->infoFromString($contents);
- } else { // new way
- require_once 'PEAR/PackageFile.php';
- $z = &PEAR_Config::singleton();
- $pkg = &new PEAR_PackageFile($z);
- $pf = &$pkg->fromXmlString($contents, PEAR_VALIDATE_DOWNLOADING, $path . $packagefile);
- if (PEAR::isError($pf)) {
- return $pf;
- }
- if ($pf->getPackagexmlVersion() != '1.0') {
- return PEAR::raiseError('PEAR_PackageFileManager can only manage ' .
- 'package.xml version 1.0, use PEAR_PackageFileManager_v2 for newer' .
- ' package files');
- }
- $this->_oldPackageXml =
- $this->_packageXml = $pf->toArray();
- }
- if (PEAR::isError($this->_packageXml)) {
- return $this->_packageXml;
- }
- if ($this->_options['cleardependencies']) {
- $this->_packageXml['release_deps'] = $this->_options['deps'];
- }
- if ($this->_options['deps'] !== false) {
- $this->_packageXml['release_deps'] = $this->_options['deps'];
- } else {
- if (isset($this->_packageXml['release_deps'])) {
- $this->_options['deps'] = $this->_packageXml['release_deps'];
- }
- }
- if ($this->_options['maintainers'] !== false) {
- $this->_packageXml['maintainers'] = $this->_options['maintainers'];
- } else {
- $this->_options['maintainers'] = $this->_packageXml['maintainers'];
- }
- unset($this->_packageXml['filelist']);
- unset($this->_packageXml['provides']);
- }
- return true;
- } else {
- if (!is_string($path)) {
- $path = gettype($path);
- }
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_PATH_DOESNT_EXIST,
- $path);
- }
- }
-
- /**
- * Create the structure for a new package.xml
- *
- * @uses $_packageXml emulates reading in a package.xml
- * by using the package, summary and description
- * options
- * @return true|PEAR_Error
- * @access private
- */
- function _generateNewPackageXML()
- {
- $this->_oldPackageXml = false;
- if (!isset($this->_options['package'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOPACKAGE);
- }
- if (!isset($this->_options['summary'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NOSUMMARY);
- }
- if (!isset($this->_options['description'])) {
- return $this->raiseError(PEAR_PACKAGEFILEMANAGER_NODESC);
- }
- $this->_packageXml = array();
- $this->_packageXml['package'] = $this->_options['package'];
- $this->_packageXml['summary'] = $this->_options['summary'];
- $this->_packageXml['description'] = $this->_options['description'];
- $this->_packageXml['changelog'] = array();
- if ($this->_options['deps'] !== false) {
- $this->_packageXml['release_deps'] = $this->_options['deps'];
- } else {
- $this->_packageXml['release_deps'] = $this->_options['deps'] = array();
- }
- if ($this->_options['maintainers'] !== false) {
- $this->_packageXml['maintainers'] = $this->_options['maintainers'];
- } else {
- $this->_packageXml['maintainers'] = $this->_options['maintainers'] = array();
- }
- return true;
- }
- }
-
- if (!function_exists('file_get_contents')) {
- /**
- * @ignore
- */
- function file_get_contents($path, $use_include_path = null, $context = null)
- {
- $a = @file($path, $use_include_path, $context);
- if (is_array($a)) {
- return implode('', $a);
- } else {
- return false;
- }
- }
- }
- ?>